#include "ListaAsoc.h"
#include "Cinta.h"
#include "cr.h"
#include "cw.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "error.h"

struct sListaAsoc
{
	Cinta cinta;
	int tam;
};

/* constructor */
ListaAsoc
la_empty (void)
{
	aList lista = NULL;
	ListaAsoc l = NULL;

	l=(ListaAsoc)calloc(1,sizeof(struct sListaAsoc));
	if(l == NULL)
		return NULL;
	lista = aList_vacia();
	l -> cinta = cinta_create( lista);
	aList_destroy(lista);
	l -> tam=0;
	return l;
}


/* agrega una clave y un dato */
void
la_add (ListaAsoc l, Key k, Data d)
{
	Tuple t = tuple_fromKeyData(k,d);
	cinta_ins( l->cinta,t);
	l -> tam = l -> tam + 1;
	tuple_destroy(t);
}

Bool
la_exists (ListaAsoc l, Key k)
{
	Key k2 = NULL;
	Bool b = FALSE;
	if(l!=NULL || k!=NULL){
		cinta_arr(l -> cinta);
		while ((!cinta_fin(l -> cinta))&&(b==FALSE))
		{
			k2 = tuple_fst(cinta_elec(l -> cinta));
			if (!key_eq(k,k2))
			{
				cinta_av(l -> cinta);
			}
			b = key_eq(k,k2);
			key_destroy( k2);
		}
	}	
	return b;
}


Data
la_search (ListaAsoc l, Key k)
{
	Data aux = NULL;
	if(la_exists(l,k))
		aux = tuple_snd(cinta_elec(l -> cinta));
	return aux;
}	


void
la_del (ListaAsoc l, Key k)
{
	if(la_exists(l,k)){
		l -> tam= l -> tam - 1;
		cinta_del(l->cinta);
	}else{
		warn(ERRFMT,"la_del: key not found",__LINE__);
	}
}



int
la_length (ListaAsoc l)
{
	if(l == NULL)
		return -1;
	else
		return l -> tam;
}

void
la_pprint (ListaAsoc l)
{
	int i=0;
	char ptr[KEY_MAX_LENGTH];
	char *ptr2;
	Key k = NULL;
	Data d = NULL;
	Tuple t = NULL;
	cinta_arr(l -> cinta);
	for(;i<l -> tam;i++)
	{
		t = cinta_elec(l -> cinta);
		k=tuple_fst(t);
		d=tuple_snd(t);
		key_toString(k,ptr);
		ptr2=data_toString(d);
		printf("(%s , %s)\n",ptr,ptr2);
		key_destroy(k);
		data_destroy(d);
		free(ptr2);
		cinta_av(l -> cinta);
	}
}


ListaAsoc
la_destroy(ListaAsoc l)
{
	aList p = NULL;
    p = cinta_destroy(l -> cinta);
	p = aList_destroy(p);
	free(l);
    l = NULL;
	return NULL;
}

ListaAsoc
la_fromFile(char *nomfile)
{
	ListaAsoc l = la_empty();
	cr c_disco = cr_create(nomfile);
	if (c_disco == NULL)
    	{
		warn(ERRFMT,"la_fromFile: no existe el archivo",__LINE__);
	}
	else
	{
		cr_arr(c_disco);
		cinta_arr(l -> cinta);

		while(!cr_fin(c_disco))
		{
			cinta_ins (l -> cinta , cr_elec(c_disco));
			l -> tam = l -> tam + 1;
			cr_av(c_disco);
		}
	c_disco = cr_destroy(c_disco);
	}
	return l;
}

void
la_toFile (char *nomfile, ListaAsoc l)
{
	cw c_disco = cw_create(nomfile);

	if (l == NULL)
		warn(ERRFMT,"la_toFile: la lista es vacía\n",__LINE__);

	cw_arr(c_disco);
	cinta_arr(l -> cinta);

	while(!cinta_fin(l -> cinta))
	{
		cw_ins(c_disco , cinta_elec(l -> cinta));
		cinta_av(l -> cinta);
	}

	c_disco = cw_destroy(c_disco);
}

void
la_toCinta(cw c_disco, ListaAsoc l)
{
	if (l == NULL)
		warn(ERRFMT,"la_toFile: la lista es vacia\n",__LINE__);

	cinta_arr(l -> cinta);

	while(!cinta_fin(l -> cinta))
	{
		cw_ins(c_disco , cinta_elec(l -> cinta));
		cinta_av(l -> cinta);
	}
}
